package com.shuai.jit.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shuai.jit.entity.History;
import com.shuai.jit.entity.course.Article;
import com.shuai.jit.entity.course.Comment;
import com.shuai.jit.entity.course.Good;
import com.shuai.jit.entity.course.Tag;
import com.shuai.jit.entity.user.User;
import com.shuai.jit.entity.vo.VoArticle;
import com.shuai.jit.mapper.*;
import com.shuai.jit.service.ArticleService;
import com.shuai.jit.mapper.vo.VoArticleMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.mahout.cf.taste.impl.common.FastByIDMap;
import org.apache.mahout.cf.taste.impl.common.LongPrimitiveIterator;
import org.apache.mahout.cf.taste.impl.model.GenericDataModel;
import org.apache.mahout.cf.taste.impl.model.GenericUserPreferenceArray;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.EuclideanDistanceSimilarity;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.model.PreferenceArray;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;


@Slf4j
@Service
@Transactional
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Autowired
    GoodMapper goodMapper;

    @Autowired
    VoArticleMapper voArticleMapper;

    @Autowired
    TagMapper tagMapper;

    @Autowired
    CommentMapper commentMapper;

    @Autowired
    HistoryMapper historyMapper;

    @Autowired
    UserMapper userMapper;

    /**
     * 添加文章
     *
     * @param article
     * @return
     */
    @Override
    public Integer add(Article article) {
        article.setArticleBad(0);
        article.setArticleStar(0);
        article.setArticleGood(0);
        article.setArticleViews(0);
        int result = this.baseMapper.insert(article);

        String id = article.getId();
        // 添加tag 信息
        if (article.getTags() != null) {

            for (String t : article.getTags()) {
                Tag tag = new Tag();
                tag.setPid(id);
                tag.setName(t);
                tagMapper.insert(tag);
            }
        }
        return result;
    }


    /**
     * 查找所有文章
     *
     * @return
     */
    @Override
    public IPage<VoArticle> selectAll(Integer current) {
        if(current==null){
            return null;
        }
        Page<Article> page = new Page<>(current, 8);
        IPage<VoArticle> list= voArticleMapper.selectAll(page);

        if (list != null) {
            for (int i = 0; i < list.getRecords().size(); i++) {
                QueryWrapper<Comment> commentQueryWrapper = new QueryWrapper<>();
                commentQueryWrapper.eq("comment_pid", list.getRecords().get(i).getId());
                list.getRecords().get(i).setArticleComment(commentMapper.selectCount(commentQueryWrapper));
            }
        }
        return list;
    }

    /**
     * 根据文章id来查找文章
     *
     * @param id
     * @return
     */
//    @Override
//    public VoArticle selectById(String id,String userId) {
//        Article article = this.baseMapper.selectById(id);
//        // 有此文章
//        if (article != null) {
//            // 增添浏览量
//            article.setArticleViews(article.getArticleViews() + 1);
//            this.baseMapper.updateById(article);
//            return voArticleMapper.selectByArticleId(id);
//        }
//        return null;
//    }

    /**
     * 根据用户id ，来查找用户所有文章
     *
     * @param userId
     * @return
     */
    @Override
    public List<Article> selectByUserId(String userId) {
        QueryWrapper<Article> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id", userId);
        return this.baseMapper.selectList(queryWrapper);
    }

    /**
     * 删除文章已经所有的tag信息
     *
     * @param id
     * @return
     */
    @Override
    public Integer delete(String id) {
        int result = this.baseMapper.deleteById(id);
        QueryWrapper<Tag> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pid", id);
        result += tagMapper.delete(queryWrapper);
        return result;
    }

    /**
     * 更新文章信息
     *
     * @param article
     * @return
     */
    @Override
    public Integer update(Article article) {
        return this.baseMapper.updateById(article);
    }


    /**
     * 如果已经点赞了，就取消点赞
     * 如果没有点赞，就添加点赞
     *
     * @param userId
     * @param article_id
     * @return
     */
    @Override
    public Integer good(String userId, String article_id) {

        if (userId == null || article_id == null) {
            return -2;
        }

        Article article = this.baseMapper.selectById(article_id);
        int result = 0;
        // 如果这个文章存在的话
        if (article != null) {
            QueryWrapper<Good> queryWrapper = new QueryWrapper<>();
            queryWrapper
                    .eq("user_id", userId)
                    .eq("pid", article_id);
            Good good = goodMapper.selectOne(queryWrapper);

            // 说明存在，已经点过赞了
            if (good != null) {
                // 取消该用户对于文章的点赞
                Integer number = article.getArticleGood();
                article.setArticleGood(number - 1);
                result = this.baseMapper.updateById(article);
                result = goodMapper.deleteById(good.getId());
            } else {
                good = new Good();
                good.setPid(article_id);
                good.setUserId(userId);
                goodMapper.insert(good);
                article.setArticleGood(article.getArticleGood() + 1);
                result = this.baseMapper.updateById(article);
            }
            return result;
        }
        return -2;
    }

    @Override
    public Integer isGood(String userId, String articleId) {
        if (userId == null || articleId == null) {
            return -1;
        }
        QueryWrapper<Good> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("user_id", userId)
                .eq("pid", articleId);
        Good good = goodMapper.selectOne(queryWrapper);
        if (good != null) {
            return 1;
        } else {
            return -1;
        }
    }

    @Override
    public List<VoArticle> getArticle(String userId) {
        try {
            FastByIDMap<PreferenceArray> preMap = new FastByIDMap<>();
            // 首先放自己的行为
            List<History> histories = historyMapper.getHistoryByUserId(userId);
            if(histories==null||histories.size()<=0){
                // 如果是新用户的话，就没有历史记录，直接返回首页页面
                return selectAll(new Random().nextInt(5)).getRecords();
            }
            PreferenceArray user1 = new GenericUserPreferenceArray(100);
            int temp = 0;
            for (History history : histories) {
                user1.setUserID(temp, Long.parseLong(history.getUserId()));
                user1.setItemID(temp, Long.parseLong(history.getPid()));
                user1.setValue(temp, new Random().nextLong() % 10);
                temp++;
            }
            preMap.put(Long.parseLong(userId), user1);

            // 随机抽取40个用户
            // 每个用户大概100 条数据 ，一次从5000条数据中查找
            Page<User> userPage = new Page<>(new Random().nextInt(8), 40);
            List<User> users = userMapper.selectPage(userPage, null).getRecords();
            for (User user : users) {
                histories = historyMapper.getHistoryByUserId(user.getId());
                user1 = new GenericUserPreferenceArray(100);
                temp = 0;
                for (History history : histories) {
                    user1.setUserID(temp, Long.parseLong(history.getUserId()));
                    user1.setItemID(temp, Long.parseLong(history.getPid()));
                    user1.setValue(temp, new Random().nextLong() % 10);
                    temp++;
                }
                preMap.put(Long.parseLong(user.getId()), user1);
            }
            DataModel model = new GenericDataModel(preMap);
            // 皮尔深算法
            PearsonCorrelationSimilarity user = new PearsonCorrelationSimilarity(model);
            // 选择2个相似度较高的参评
            NearestNUserNeighborhood neighbor = new NearestNUserNeighborhood(2, user, model);
            //用户近邻算法
            Recommender r = new GenericUserBasedRecommender(model, neighbor, user);//用户推荐算法
            // 推荐8篇文章
            List<RecommendedItem> list = r.recommend(Long.parseLong(userId), 8);
            List<VoArticle> articles = new ArrayList<>();
            for (RecommendedItem ritem : list) {
                VoArticle article=selectById(String.valueOf(ritem.getItemID()), userId);
                if(article!=null){
                    articles.add(article);
                }
            }
            return articles;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 根据用户历史，来浏览
     *
     * @param id
     * @param userId
     * @return
     */
    @Override
    public VoArticle selectById(String id, String userId) {
        Article article = this.baseMapper.selectById(id);
        // 有此文章
        if (article != null) {
            // 增添浏览量
            article.setArticleViews(article.getArticleViews() + 1);
            // 设置浏览历史
            if(userId!=null){
                History history = new History();
                history.setPid(id);
                history.setUserId(userId);
                historyMapper.insert(history);
            }
            // 更新浏览量
            this.baseMapper.updateById(article);
            return voArticleMapper.selectByArticleId(id);
        }
        return null;
    }
}
